package org.cybzacg.convert.converters.gather;

import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.exception.ConversionException;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;

/**
 * 集合转换器抽象基类
 * 为List、Set、Queue等集合转换器提供公共逻辑
 *
 * <p>
 * 类型安全说明：
 * <ul>
 * <li>集合元素在转换过程中不进行类型检查</li>
 * <li>源集合元素类型应与目标集合兼容</li>
 * <li>不兼容的类型可能在后续使用时抛出 ClassCastException</li>
 * <li>建议在使用前确保源数据类型正确</li>
 * </ul>
 *
 * @param <C> 集合类型
 * @author cybzacg.blog
 * @version 4.0
 * @since 4.0
 */
@Slf4j
public abstract class AbstractCollectionConverter<C extends Collection<Object>> extends AbstractTypeConverter {

    private final Class<?> collectionType;

    protected AbstractCollectionConverter(Class<?> collectionType, ConversionPriority priority) {
        super(priority);
        this.collectionType = collectionType;
        log.debug("{} 初始化完成，优先级: {}", getClass().getSimpleName(), priority);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected <T> T doConvert(Object source, Class<T> targetType, T defaultValue, ConversionContext context)
            throws Exception {

        log.debug("开始{}转换: 源类型={}, 目标类型={}",
                getCollectionTypeName(),
                source != null ? source.getClass().getSimpleName() : "null",
                targetType.getSimpleName());

        if (source == null) {
            log.debug("源对象为null，返回默认值: {}", defaultValue);
            return defaultValue;
        }

        // 如果已经是目标类型，直接返回
        if (targetType.isInstance(source)) {
            log.debug("源对象已经是目标类型，直接返回");
            return (T) source;
        }

        // 转换为集合
        C result = convertToCollection(source, targetType, context);
        log.debug("{}转换完成: {} -> {}", getCollectionTypeName(),
                source.getClass().getSimpleName(), result.getClass().getSimpleName());

        return (T) result;
    }

    /**
     * 将对象转换为集合
     */
    @SuppressWarnings("unchecked")
    protected <T> C convertToCollection(Object source, Class<T> targetType, ConversionContext context)
            throws ConversionException {

        if (source == null) {
            return createEmptyCollection(targetType);
        }

        // 数组转集合
        if (source.getClass().isArray()) {
            return convertArrayToCollection(source, targetType, context);
        }

        // 集合转集合
        if (source instanceof Collection) {
            return convertCollectionToCollection((Collection<?>) source, targetType, context);
        }

        // Map转集合
        if (source instanceof Map) {
            return convertMapToCollection((Map<?, ?>) source, targetType, context);
        }

        // 字符串转集合
        if (source instanceof String) {
            return convertStringToCollection((String) source, targetType, context);
        }

        // 单个对象转集合
        return convertObjectToCollection(source, targetType, context);
    }

    /**
     * 数组转集合
     */
    protected <T> C convertArrayToCollection(Object array, Class<T> targetType, ConversionContext context) {
        C collection = createEmptyCollection(targetType);

        if (array instanceof Object[]) {
            Object[] objArray = (Object[]) array;
            for (Object item : objArray) {
                collection.add(item);
            }
        } else {
            // 基本类型数组
            int length = Array.getLength(array);
            for (int i = 0; i < length; i++) {
                collection.add(Array.get(array, i));
            }
        }

        return collection;
    }

    /**
     * 集合转集合
     */
    protected <T> C convertCollectionToCollection(Collection<?> source, Class<T> targetType,
            ConversionContext context) {
        C collection = createEmptyCollection(targetType);
        collection.addAll(source);
        return collection;
    }

    /**
     * Map转集合
     */
    protected <T> C convertMapToCollection(Map<?, ?> source, Class<T> targetType, ConversionContext context) {
        C collection = createEmptyCollection(targetType);

        // 根据上下文决定转换方式
        String mapConversionMode = context.getProperty("mapConversionMode");
        if (mapConversionMode == null) {
            mapConversionMode = getDefaultMapConversionMode();
        }

        switch (mapConversionMode.toLowerCase()) {
            case "keys":
                collection.addAll(source.keySet());
                break;
            case "values":
                collection.addAll(source.values());
                break;
            case "entries":
            default:
                collection.addAll(source.entrySet());
                break;
        }

        return collection;
    }

    /**
     * 字符串转集合
     */
    protected <T> C convertStringToCollection(String source, Class<T> targetType, ConversionContext context) {
        C collection = createEmptyCollection(targetType);

        if (source == null || source.trim().isEmpty()) {
            return collection;
        }

        String str = source.trim();

        // 尝试解析JSON格式
        if ((str.startsWith("[") && str.endsWith("]")) ||
                (str.startsWith("{") && str.endsWith("}"))) {
            log.debug("检测到JSON格式字符串，可能需要JSON解析");
        }

        // 使用分隔符分割
        String delimiter = context.getProperty("delimiter");
        if (delimiter == null) {
            delimiter = ",";
        }

        String[] items = str.split(delimiter);
        for (String item : items) {
            String trimmed = item.trim();
            if (!trimmed.isEmpty()) {
                collection.add(trimmed);
            }
        }

        return collection;
    }

    /**
     * 单个对象转集合
     */
    protected <T> C convertObjectToCollection(Object source, Class<T> targetType, ConversionContext context) {
        C collection = createEmptyCollection(targetType);
        collection.add(source);
        return collection;
    }

    /**
     * 创建空集合（由子类实现）
     */
    protected abstract <T> C createEmptyCollection(Class<T> targetType);

    /**
     * 获取默认的Map转换模式（由子类实现）
     */
    protected abstract String getDefaultMapConversionMode();

    /**
     * 获取集合类型名称（用于日志）
     */
    protected String getCollectionTypeName() {
        return collectionType.getSimpleName();
    }

    @Override
    public boolean supports(Class<?> targetType) {
        return collectionType.isAssignableFrom(targetType);
    }

    @Override
    public Class<?> getSupportedType() {
        return collectionType;
    }

    @Override
    public abstract String getName();
}
